const multiparty = require('multiparty')
const { resolve, join } = require('path')
const fs = require('fs');
const { format } = require('../tool/tool.js');

// 跟踪文件上传进度  
let uploadStatuses = {};

module.exports = {
  index(req, resp) {
    // 重新定向
    resp.redirect(301, '/pages/updateFiles.html');
  },
  shardUpload(req, res) {
    // req.files.chunk 是分片文件  
    let name = req.body.name;// req.body.name 是文件名 
    let formatTime = req.body.formatTime;// req.body.name 是上传时的时间
    let index = parseInt(req.body.index, 10);// req.body.index 是分片索引  
    let chunks = parseInt(req.body.chunks, 10);// req.body.chunks 是总分片数  

    // 初始化文件状态（如果尚未存在）  
    if (!uploadStatuses[name]) {
      uploadStatuses[name] = {
        totalChunks: chunks, uploadedChunks: 0,
        chunks: Array(chunks).fill(false) // 使用数组来跟踪每个分片的上传状态  
      };
    }
    // 标记该分片为已上传  
    uploadStatuses[name].chunks[index] = true;
    uploadStatuses[name].uploadedChunks++;
    // 检查是否所有分片都已上传  
    if (uploadStatuses[name].uploadedChunks === chunks) {
      // 所有分片都已上传，执行合并操作...  
      mergeChunks(name, chunks, formatTime)
        .then(() => {
          // 合并成功，删除文件状态  
          delete uploadStatuses[name];
          // 在合并后删除分片文件 
          deleteChunks(name, chunks)
        })
        .catch(error => { });// 合并失败，处理错误... 
      res.status(200);
      res.send(JSON.stringify({
        status: 1,
        success: true,
        message: '分片已经全部上传完~~',
      }))
    } else {
      // 分片未全部上传，返回响应  
      // res.send('Chunk received');
      // return
      res.status(200);
      res.send(JSON.stringify({
        status: 0,
        success: true,
        message: '分片未全部上传完~',
      }))
    }
  },
  showFiles(req, resp) {
    let { username } = req.query
    username = decodeURIComponent(username)
    // join(__dirname, '../src/files'
    let saveFilesPath = resolve('./', 'src', 'files');
    fs.stat(saveFilesPath, async function (err, stats) {
      if (!stats) { // 路径不存在
        resp.send(JSON.stringify({
          status: 0,
          success: false,
          message: '\n该用户没有缓存的文件。\n\n创建新用户分享给朋友上传文件吧！',
        }, null, 2))
      } else {
        let filesList = getAllFiles(saveFilesPath)
        // console.log('filesList', filesList)
        if (filesList.length == 0) {
          resp.send(JSON.stringify({
            status: 0,
            success: false,
            message: '没有查找到文件',
          }, null, 2))
        } else {
          resp.send(JSON.stringify({
            status: 1,
            success: true,
            message: '查找到如下文件',
            filesList
          }, null, 2))
        }
      }
    });

  },
  deleteFile(req, resp) {
    /* 删除文件 */
    let { delFileName } = req.query
    let saveFilesPath = resolve('./', 'src', 'files', delFileName);
    let flag = fs.existsSync(saveFilesPath) // 这是同步。
    if (flag) {
      fs.unlink(saveFilesPath, (err) => {
        if (err) {
          resp.send(JSON.stringify({
            status: 0,
            success: false,
            message: '没有查找到文件，删除失败1',
          }, null, 2))
          return;
        }
        resp.send(JSON.stringify({
          status: 1,
          success: true,
          message: '删除文件成功',
          delFileName
        }, null, 2))
      })
    } else {
      resp.send(JSON.stringify({
        status: 0,
        success: false,
        message: '没有查找到文件，删除失败2',
      }, null, 2))
    }
  },
}

// 定时刷新，每隔1天就删除缓存文件时长超过1天的文件
setInterval(() => {
  console.log('缓存文件开始刷新============',)
  let saveFilesPath = resolve('./', 'src', 'files');
  let deleteFilesTime = 1000 * 60 * 60 * 24 * 30; // 删除文件和文件夹的时间，一个月
  fileDisplay(saveFilesPath, (obj) => {
    let { folderPath, folderOrFile_s, folderOrFile, real_Path, stats } = obj;
    let tt = new Date().getTime() - new Date(stats.ctime).getTime()
    if (stats.isFile()) {
      if (tt - deleteFilesTime > 0)
        console.log(`删除 ${real_Path} 文件`),
          fs.rm(real_Path, {
            force: true, recursive: true
          }, (err) => { err && console.log('fs.rm:err:--=- ', real_Path, err) })
    }
    if (stats.isDirectory()) {
      // 如果缓存文件的时长大于规定天数，则进行删除文件夹操作
      if (tt - (deleteFilesTime) > 0)
        console.log(`删除 ${real_Path} 文件夹`),
          fs.rmdir(real_Path, (err) => { err && console.log('fs.unlink:err== ', real_Path, err); return true })
    }
  })
}, 1000 * 60 * 60);


// ===========================================================
// ===========================================================
// ===========================================================

/** 
 * 文件遍历方法 和 删除文件夹及文件 
 * @param folderPath 需要遍历的文件夹路径 
 */
function fileDisplay(folderPath, callback = () => { }) {
  //根据文件路径读取文件，返回文件路径下一级的所有文件及文件夹列表  
  fs.readdir(folderPath, function (err, folderOrFile_s) {
    if (err) console.warn(err)
    else {
      //遍历读取到的文件及文件夹列表  
      folderOrFile_s.forEach(function (folderOrFile) {
        //获取当前文件或文件夹的绝对路径  
        var real_Path = join(folderPath, folderOrFile);
        //根据文件路径获取文件信息，返回一个fs.Stats对象  
        fs.stat(real_Path, function (eror, stats) {
          if (eror) console.warn('获取文件stats失败');
          else {
            if (stats.isDirectory()) fileDisplay(real_Path, callback) //如果是文件夹，就继续遍历该文件夹下面的文件
            callback({
              folderPath, folderOrFile_s, folderOrFile, real_Path, stats
            })
          }
        })
      });
    }
  });
}

// 定义获取文件夹下所有的文件的方法
function getAllFiles(root) {
  var res = [], files = fs.readdirSync(root);
  files.forEach(function (file) {
    var pathname = root + '/' + file
      , stat = fs.lstatSync(pathname);
    if (!stat.isDirectory()) {
      res.push(file);
    } else {
      res = res.concat(getAllFiles(pathname));
    }
  });
  return res
}

// 传入文件夹的路径看是否存在，存在不用管，不存在则直接创建文件夹
let DirectoryExistenceAndCreate = async function (reaPath) {
  try {
    fs.statSync(reaPath)
  } catch (e) {
    // 不存在文件夹，直接创建 {recursive: true} 这个配置项是配置自动创建多个文件夹
    await fs.promises.mkdir(reaPath, { recursive: true })
  }
}

// 合并分片的逻辑
async function mergeChunks(fileName, chunkCount, formatTime) {
  return new Promise(async (resolve, reject) => {
    await DirectoryExistenceAndCreate(join(__dirname, '../src/files'));
    // 最终要保存到的位置，文件名格式：日期_时间_文件名
    const outputStream = fs.createWriteStream(join(__dirname, '../src/files', `${formatTime}_${fileName}`));
    for (let i = 0; i < chunkCount; i++) {
      const chunkPath = join(__dirname, '../temp', `temp-${fileName}-${chunkCount}-${i}`);
      try {
        // 不能用异步，会导致写入数据的顺序错乱
        outputStream.write(fs.readFileSync(chunkPath));
        if (i === chunkCount - 1) {
          // 所有分片都已写入，关闭输出流  
          outputStream.end();
          // console.log(`合并文件成功： ${fileName} `);
          resolve(`成功`)
        }
      } catch (error) {
        reject(`失败:` + error);
      }
    }
  })
}

// 删除所有分片文件  
function deleteChunks(fileName, chunkCount) {
  for (let j = 0; j < chunkCount; j++) {
    const toDelete = join(__dirname, '../temp', `temp-${fileName}-${chunkCount}-${j}`);
    fs.unlink(toDelete, (err) => {
      // if (err) { console.error(`Error deleting chunk ${toDelete}:`, err); }
      // else { console.log(`Chunk ${toDelete} deleted successfully.`); }
    });
  }
}